import dayjs from 'dayjs';
import jsonwebtoken from 'jsonwebtoken';
import bcrypt from 'bcrypt';
import User from '@/model/User';
import config from '@/config';

class LoginController {
  /**
   * 登录接口
   *
   * + 接收用户数据
   * + 返回token
   */
  async login(ctx) {
    const { body } = ctx.request;
    const { username, password } = body;

    const user = await User.findOne({ username });
    let checkUserPassword = '';

    /**
     * 解密密码: 第一参数是明文密码，第二参数是哈希密码。
     *
     * 为什么解密不需要salt？
     * 答：bcrypt在生成哈希密码时，已将salt编码(base64编码)，并作为哈希密码的一部分存储在数据库中。
     */
    if (await bcrypt.compare(password, user.password)) {
      checkUserPassword = true;
    }

    if (checkUserPassword) {
      // Mongoose提供了toJSON方法，将文档转换成JSON对象
      const userObj = user.toJSON();
      // 删除敏感信息
      const arrs = ['password', 'username', 'mobile', 'roles'];
      arrs.map((item) => {
        delete userObj[item];
      });

      // 验证通过，返回Token值
      const token = jsonwebtoken.sign({ _id: userObj._id }, config.JWT_SECRET, {
        expiresIn: '1d',
      });

      ctx.body = {
        code: 200,
        data: userObj,
        token: token,
      };
    } else {
      // 用户名/密码验证失败
      ctx.body = {
        code: 404,
        msg: '用户名或密码错误',
      };
    }
  }

  // 注册
  async reg(ctx) {
    const { body } = ctx.request;
    const { username, name, password } = body;
    let check = true;
    let msg = '';

    // 进行去重校验：邮箱
    const user1 = await User.findOne({ username });
    if (user1 !== null && typeof user1.username !== 'undefined') {
      check = false;
    }

    // 进行去重校验：昵称
    const user2 = await User.findOne({ name });
    if (user2 !== null && typeof user2.name !== 'undefined') {
      check = false;
    }

    if (check) {
      // 生成hash密码。其中 5 代表hash杂凑次数，数值越高越安全，默认 10 次。
      const cryptPassword = await bcrypt.hash(password, 5);
      const user = new User({
        username,
        name,
        password: cryptPassword,
        created: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      });

      const res = await user.save();

      ctx.body = {
        code: 200,
        data: res,
        msg: '注册成功',
      };

      return;
    } else {
      msg = '请更换邮箱或者昵称，当前邮箱/昵称已注册';
    }

    ctx.body = {
      code: 500,
      msg,
    };
  }
}

export default new LoginController();
